<?php

declare(strict_types=1);

namespace Modules\DataCheck\Http\Controllers;

use Catch\Exceptions\FailedException;
use Catch\Facade\Admin;
use Modules\DataCheck\Enums\TaskStateEnum;
use Modules\DataCheck\Models\DcTask;
use Modules\DataCheck\Models\DcTaskTargetDownloadLog;
use Illuminate\Http\Request;
use Pro\Support\Helper;

/**
 * 数据核对任务目标数据下载控制器
 * 
 * 提供任务结果文件下载和下载日志记录功能
 */
class DownloadController extends BaseController
{
    /**
     * 构造函数
     * 
     * @param DcTaskTargetDownloadLog $model 下载日志模型实例
     */
    public function __construct(protected readonly DcTaskTargetDownloadLog $model)
    {

    }

    /**
     * 执行任务结果文件下载
     * 
     * 验证任务状态并记录下载日志，返回文件下载地址
     * 
     * @param Request $request HTTP请求对象
     * @return array 包含文件下载地址的响应数据
     * @throws FailedException 当任务不存在、状态异常或下载失败时抛出异常
     */
    public function execute(Request $request){
        // 验证必需参数task_id是否存在
        if (empty($taskId = $request->input('task_id'))) {
            throw new FailedException('task_id：任务ID不能为空');
        }
        
        // 查询任务信息
        $task = DcTask::query()->where('task_id', $taskId)->select(['id','task_state','file_download_url'])->first();
        if (empty($task)) {
            throw new FailedException('任务不存在');
        }
        
        // 检查任务状态是否已完成
        if($task->task_state != TaskStateEnum::COMPLETE->value){
            throw new FailedException('任务状态异常，无发进行下载');
        }
        
        // 检查下载地址是否存在
        if(empty($task->file_download_url)){
            throw new FailedException('任务文件下载地址不存在');
        }
        
        // 查询文件当前的下载次数
        $curCount = DcTaskTargetDownloadLog::query()->where('task_id', $taskId)->count();
        
        // 开启事务进行下载统计和日志记录
        $this->model->beginTransaction();
        try{
            // 更新任务的下载次数
            DcTask::query()->where(['task_id' => $taskId])->update(['file_download_count' => $curCount+1]);
            
            // 记录下载日志
            $log = [
                'task_id' => $taskId, 
                'creator_id' => Admin::id(),
                'ip' => Helper::getClientIp()
            ];
            $logObj = $this->model->create($log);
            
            // 提交事务
            $this->model->commit();
        }catch (\Throwable $e){
            // 回滚事务并抛出异常
            $this->model->rollBack();
            throw new FailedException("核对结果下载失败：".$e->getMessage());
        }
        //记录管理员行为
        request()->attributes->set('behavior', [
            'module'     => '数据核对',
            'business'   => '任务管理',
            'operation'  => "任务结果文件下载（任务id：{$taskId}）",
            'related_id' => $logObj->id
        ]);
        // 返回文件下载地址
        return ['file_download_url'=>$task->file_download_url];
    }

    /**
     * 下载日志列表
     *
     * @param Request $request
     * @return mixed
     */
    /**
     * 获取下载日志列表
     *
     * @param Request $request HTTP请求对象
     * @return mixed 分页数据结果
     * @throws FailedException 当task_id参数为空时抛出异常
     */
    public function logs(Request $request): mixed
    {
        // 验证必需参数task_id是否存在
        if (empty($request->input('task_id'))) {
            throw new FailedException('task_id：任务ID不能为空');
        }
        // 使用CatchAdmin规范：通过setBeforeGetList处理关联关系，然后返回分页数据
        $paginator =  $this->model->setBeforeGetList(function ($query){
            // 构建查询关联关系
            $query->from('dc_task_target_download_log')
                   ->join('dc_task', 'dc_task.task_id', '=', 'dc_task_target_download_log.task_id')
                   ->leftJoin('admin_users', 'dc_task_target_download_log.creator_id', '=', 'admin_users.id');
            // 选择需要返回的字段
            $query->select([
                'dc_task_target_download_log.creator_id AS create_user_id',
                'admin_users.username AS create_user_name',
                'dc_task_target_download_log.created_at AS created_at',
                'dc_task_target_download_log.ip AS ip',
            ]);
            return $query;
        })->getList();
        
        // 获取分页信息用于序列号计算
        $currentPage = $paginator->currentPage(); // 当前页码（从 1 开始）
        $perPage = $paginator->perPage(); // 每页显示的条数
        
        // 对结果集进行后处理，添加序列号和格式化时间字段
        $paginator->getCollection()->transform(function ($item, $index) use ($currentPage, $perPage) {
            // 计算并添加序列号：(当前页-1)*每页条数 + 索引（从0开始） + 1
            $serialNumber = ($currentPage - 1) * $perPage + $index + 1;
            $item->serial_number = $serialNumber;
            
            // 格式化创建时间字段为日期和时间两个独立字段
            $item->created_at_ymd = $item->created_at->format('Y-m-d');
            $item->created_at_his = $item->created_at->format('H:i:s');
            
            // 移除原始的created_at字段
            unset($item->created_at);
            
            return $item;
        });
        
        return $paginator;
    }

}